package com.whcoding.base.project.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.whcoding.base.project.annotion.NotControllerResponseAdvice;
import com.whcoding.base.project.common.api.BaseResultVO;
import com.whcoding.base.project.common.api.ResultStatusEnum;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @program: spring-boot-learning
 * @description: 针对controller 统一封装返回的状态值
 * @author: whcoding
 * @create: 2022-06-30 11:38
 **/
@RestControllerAdvice(basePackages = {"com.whcoding.base.project.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

	/**
	 * 前置操作
	 * @param methodParameter
	 * @param aClass
	 * @return
	 */
	@Override
	public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
		// response是ResultVo类型，或者注释了NotControllerResponseAdvice都不进行包装
		if (methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class)){
			return false;
		}
		return !methodParameter.getParameterType().isAssignableFrom(BaseResultVO.class);
	}

	/**
	 * 后置操作
	 * @param data
	 * @param returnType
	 * @param mediaType
	 * @param aClass
	 * @param request
	 * @param response
	 * @return
	 */
	@Override
	public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
		// String类型不能直接包装
		if (returnType.getGenericParameterType().equals(String.class)) {
			ObjectMapper objectMapper = new ObjectMapper();
			try {
				// 将数据包装在ResultVo里后转换为json串进行返回
				return objectMapper.writeValueAsString(BaseResultVO.success(data));
			} catch (JsonProcessingException e) {
				throw new APIException(ResultStatusEnum.RESPONSE_PACK_ERROR, e.getMessage());
			}
		}
		// 否则直接包装成ResultVo返回
		return BaseResultVO.success(data);
	}
}
